package com.leapcloud.crm.core.dto;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.leapcloud.crm.core.exception.ImsException;
import com.leapcloud.crm.core.utils.JsonUtils;
import lombok.Data;

/**
 * @author motorfu
 * @email ffu@maxleap.com
 * @since 2018/8/29 16:35
 */
@Data
public class ImsResponse<DTO> extends DTOBean {
  private int code;
  private String msg;
  private DTO data;

  @JsonInclude(JsonInclude.Include.NON_NULL)
  private Object internalMsg;
  @JsonInclude(JsonInclude.Include.NON_NULL)
  private String path;
  @JsonInclude(JsonInclude.Include.NON_NULL)
  private Long timestamp;

  public ImsResponse() {

  }

  public ImsResponse(Builder<DTO> builder) {
    this.code = builder.code;
    this.msg = builder.msg;
    this.data = builder.data;
  }

  public static <T> Builder<T> newBuilder() {
    return new Builder<T>();
  }

  public static <T> Builder<T> newBuilder(T data) {
    return new Builder<T>(data);
  }

  public static <T> Builder<T> newBuilder(T result, String errMsg) {
    return new Builder<T>(result, errMsg);
  }

  public static class Builder<T> {
    private int code = 200;

    private String msg = "success";

    private T data;

    public Builder(T result, String errMsg) {
      check(result, errMsg);
    }

    public Builder(T data) {
      this.data = data;
    }

    public Builder() {
    }

    public Builder<T> code(int code) {
      this.code = code;
      return this;
    }

    public Builder<T> msg(String msg) {
      this.msg = msg;
      return this;
    }

    public Builder<T> data(T data) {
      this.data = data;
      return this;
    }

    public Builder<T> check(T result, String errMsg) {
      if (result == null) {
        return this;
      }
      if (result instanceof Integer) {
        if (result.equals(0)) {
          this.code = 400;
          this.msg = errMsg;
        }
      } else if (result instanceof Boolean) {
        if (!((Boolean) result).booleanValue()) {
          this.code = 400;
          this.msg = errMsg;
        }
      } else {
        throw new ImsException(String.format("check 方法不支持%s类型", result.getClass().getName()));
      }
      this.data = result;
      return this;
    }

    public ImsResponse<T> failed() {
      if (this.code == 200) {
        this.code = 400;
      }
      return new ImsResponse<T>(this);
    }

    public ImsResponse<T> build() {
      return new ImsResponse<T>(this);
    }

    public String toJson() {
      return JsonUtils.encode(new ImsResponse<T>(this));
    }
  }
}
